package com.kgc.sbt.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kgc.sbt.api.UserApi;
import com.kgc.sbt.config.WechatAuthConfig;
import com.kgc.sbt.config.annotation.RequestPermission;
import com.kgc.sbt.util.HttpClient4Util;
import com.kgc.sbt.util.RequestResult;
import com.kgc.sbt.util.ResultBuildUtil;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 微信网页授权入口
 */
@RestController
@RequestMapping("/wechatAuth")
@Slf4j
@Api(tags = "用户微信授权接口，版本号：2.1.0")
public class WechatAuthController {

    @Autowired
    private JdbcTemplate jdbcTemplate;


    // 静态注入redis
    private static Jedis jedis = new Jedis("127.0.0.1", 6379);

    static {
        // 用5库进行测试
        jedis.select(0);
    }

    @Autowired
    private WechatAuthConfig wechatAuthConfig;

    @Reference
    private UserApi userApi;

    /**
     * 请求微信公众号测试平台，获取code值。
     */
    @PostMapping("/wechatCode")
    @ApiOperation(value = "微信授权", httpMethod = "POST", produces = "application/json;charset=UTF-8", notes = "微信授权登录，生成一个登录二维码。如果扫码微信还未绑定过手机号，" +
            "则登录成功后会要求绑定一个手机号再进行业务操作；如果已经绑定过手机号则，登录成功返回绑定的手机号信息。")
    public RequestResult<String> wechatGetCode() {

        // 封装获取code的请求地址
        StringBuffer codeUri = new StringBuffer(wechatAuthConfig.getCodeUri());
        codeUri.append("?appid=").append(wechatAuthConfig.getAppId())
                .append("&redirect_uri=").append(wechatAuthConfig.getRedirectUri())
                .append("&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect");
        return ResultBuildUtil.success(codeUri.toString());
    }

    /**
     * 接收微信异步回调code值，获取access_token需要用
     */
    @RequestMapping(value = "/codeCallBack", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation(value = "[请点击‘微信授权’]")
    @ApiResponse(code = 7011, message = "微信返回的code为null")
    public RequestResult<String> wechatCodeCallBack(HttpServletRequest request){
        // 官方返回示例： 如果用户同意授权，页面将跳转至 redirect_uri/?code=CODE&state=STATE。
        // code说明 ： code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。
        String wechatCode = request.getParameter("code");
//        String phone = request.getParameter("state");
        String phoneNo = "";
        String token = "";


        // 以下代码需要优化！！！

        // 验证code的合法性。
        if (StringUtils.isEmpty(wechatCode)) {
            return ResultBuildUtil.fail("7011", "微信返回的code为null");
        }

        // 通过code在发起请求到微信官方换取access_token
        StringBuffer accessTokenUrl = new StringBuffer(wechatAuthConfig.getAccessTokenUri());
        accessTokenUrl.append("?appid=").append(wechatAuthConfig.getAppId())
                .append("&secret=").append(wechatAuthConfig.getAppSecret())
                .append("&code=").append(wechatCode)
                .append("&grant_type=authorization_code");

        String resultDetail = HttpClient4Util.getResponse4GetAsString(accessTokenUrl.toString(), "UTF-8");

        // 解析返回的json字符串，获取access_token
        JSONObject jsonObject = JSON.parseObject(resultDetail);
        String access_token = jsonObject.getString("access_token");
        String openId = jsonObject.getString("openid");

        //拉取用户信息(需scope为 snsapi_userinfo)
        StringBuffer getUser = new StringBuffer(wechatAuthConfig.getGetUserInfo());
        getUser.append("?access_token=").append(access_token)
                .append("&openid=").append(openId).append("&lang=zh_CN");
        String getUserDetail = HttpClient4Util.getResponse4GetAsString(getUser.toString(), "UTF-8");

        // 如果用户手机已经绑定过微信，可以直接用微信登录
        if (StringUtils.isEmpty(userApi.queryUserByOpenid(openId))) {
            // TODO 需要去绑定手机号
            log.info("++++++++++++++++++++您已成功验证了微信帐号！马上绑定聚美帐号，下次登录更便捷哦,openid:[" + openId + "]");
            // 生成一个30分钟的openid存入redis
            jedis.setex(openId,1800, openId);
            return ResultBuildUtil.success("您已成功验证了微信帐号！马上绑定聚美帐号，下次登录更便捷哦;微信用户信息为:" + getUserDetail);

        } else {
            phoneNo = userApi.queryUserByOpenid(openId).getPhone();
            String sql = "select id from user where phone = " + phoneNo;
            int userId = jdbcTemplate.queryForObject(sql, Integer.TYPE);
            // 生成token，存入redis （key-token, value-用户信息（转json字符串））
            token = UUID.randomUUID().toString();
            jedis.set(token, JSON.toJSONString(userId));
            // 生成一个vipToken，用于检查VIP是否过期
            jedis.set("vipToken", phoneNo);
        }
        // 返回登录成功信息
        log.info("++++++++++++++登录成功！用户手机号为:" + phoneNo + ";微信用户信息为:" + getUserDetail + "登录token值是:{}", token);
        return ResultBuildUtil.success("登录成功！用户手机号为:" + phoneNo + ";微信用户信息为:" + getUserDetail + "登录token值是=" + token);
    }

    /**
     * @param:
     * @return:
     * @auther: hcc
     * @date: 2021/6/28 0028 19:48
     * 功能描述: 微信授权登录后，绑定手机号
     */
    @GetMapping("/wechatBinding")
    @ApiOperation(value = "微信登录后绑定手机号", httpMethod = "GET", notes = "微信授权登录后，如果该微信未绑定过手机号，则输入手机号进行绑定；（openid是微信登录后获取到的）, 该手机号必须是已经注册的并且未绑定过其他微信号的, 且不能重复绑定。")
    @ApiImplicitParam(name = "phoneNo", required = true, value = "手机号")
    @ApiResponses({
            @ApiResponse(code = 7755, message = "该手机号还未注册，微信授权绑定失败！"),
            @ApiResponse(code = 7754, message = "该微信已绑定过手机号，请解绑后重试。"),
            @ApiResponse(code = 7753, message = "该用户已经绑定微信号，请解绑后重试。")
    })
    public RequestResult<String> wechatBinding(String phoneNo,HttpServletRequest request) {
        String openId = jedis.get(request.getHeader("openid"));
        // 校验该openId，是否已经绑定过手机号
        if (StringUtils.isEmpty(userApi.queryUserByOpenid(openId))) {
            if (StringUtils.isEmpty(userApi.queryUser(phoneNo).getOpenid())) {
                // 添加用户openid
                if (!userApi.updateOpenId(openId, phoneNo)) {
                    return ResultBuildUtil.fail("7755", "该手机号还未注册，微信授权绑定失败！");
                } else {
                    return ResultBuildUtil.success("用户手机号与此微信绑定成功！");
                }
            } else {
                return ResultBuildUtil.fail("7753", "该用户已经绑定微信号，请解绑后重试。");
            }
        } else {
            return ResultBuildUtil.fail("7754", "该微信已绑定过手机号，请解绑后重试。");
        }

    }

    /**
     * @param:
     * @return:
     * @auther: hcc
     * @date: 2021/6/29 0029 14:59
     * 功能描述: 微信授权解绑手机号
     */
    @PostMapping("/wechatUnbind")
    @ApiOperation(value = "微信授权解绑手机号", httpMethod = "POST", notes = "登录后的用户，可以通过校验手机验证码(与该用户手机号相匹配的有效验证码)来进行微信授权解绑。")
    @ApiImplicitParam(name = "code", required = true, value = "验证码")
    @ApiResponses({
            @ApiResponse(code = 6000, message = "验证码已失效"),
            @ApiResponse(code = 6003, message = "验证码错误，请重试！")
    })
    @RequestPermission
    public RequestResult<String> wechatUnbind(@RequestParam String code, HttpServletRequest request){
        String token = request.getHeader("token");
        String phoneNo = jdbcTemplate.queryForObject("select phone from user where id = " + jedis.get(token), String.class);
        String codeKey = phoneNo + ":code";
        // 获取验证码
        String validation = jedis.get(codeKey);

        // 验证码非空判断
        if (validation == null) {
            return ResultBuildUtil.fail("6000", "验证码已失效");
        }
        // 验证码有效性判断
        if (validation.equals(code)) {

            // 解绑成功，删除验证码
            jedis.del(codeKey);

            userApi.updateWechatUnbind(phoneNo);
            return ResultBuildUtil.success("该手机号解绑成功！");
        } else {
            return ResultBuildUtil.fail("6003", "验证码错误，请重试！");
        }
    }


}
